home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 February / EnigmA AMIGA RUN 15 (1997)(G.R. Edizioni)(IT)[!][issue 1997-02][PLANET CD V].iso / enigma / earcd / emula / arosdv19.lha / AROS / exec / freemem.c < prev    next >
C/C++ Source or Header  |  1996-10-24  |  6KB  |  260 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: freemem.c,v 1.12 1996/10/24 15:50:50 aros Exp $
  4.     $Log: freemem.c,v $
  5.     Revision 1.12  1996/10/24 15:50:50  aros
  6.     Use the official AROS macros over the __AROS versions.
  7.  
  8.     Revision 1.11  1996/10/19 17:07:26  aros
  9.     Include <aros/machine.h> instead of machine.h
  10.  
  11.     Revision 1.10  1996/09/13 17:51:23  digulla
  12.     Use IPTR
  13.  
  14.     Revision 1.9  1996/09/11 16:56:16  digulla
  15.     Move PurgeChunk() to aros.lib
  16.  
  17.     Revision 1.8  1996/08/23 17:06:56  digulla
  18.     Began work on ressource tracking
  19.  
  20.     Revision 1.7  1996/08/16 14:05:12  digulla
  21.     Added debug output
  22.  
  23.     Revision 1.6  1996/08/15 14:42:15  digulla
  24.     Added comment
  25.  
  26.     Revision 1.5  1996/08/15 13:19:02  digulla
  27.     First attempt to purge memory after free to make code crash which accesses
  28.     memory after a free but just that happens in RemTask().
  29.  
  30.     Revision 1.4  1996/08/13 13:56:02  digulla
  31.     Replaced AROS_LA by AROS_LHA
  32.     Replaced some AROS_LH*I by AROS_LH*
  33.     Sorted and added includes
  34.  
  35.     Revision 1.3  1996/08/01 17:41:11  digulla
  36.     Added standard header for all files
  37.  
  38.     Desc:
  39.     Lang:
  40. */
  41. #include <exec/alerts.h>
  42. #include <exec/execbase.h>
  43. #include <aros/machine.h>
  44. #include "memory.h"
  45. #include <aros/rt.h>
  46.  
  47. #include "exec_debug.h"
  48. #ifndef DEBUG_FreeMem
  49. #   define DEBUG_FreeMem 0
  50. #endif
  51. #if DEBUG_FreeMem
  52. #   undef DEBUG
  53. #   define DEBUG 1
  54. #endif
  55. #include <aros/debug.h>
  56.  
  57. #define NASTY_FREEMEM    0    /* Delete contents of free'd memory ? */
  58.  
  59. #if NASTY_FREEMEM
  60. extern void PurgeChunk (ULONG *, ULONG);
  61. #endif
  62.  
  63. /*****************************************************************************
  64.  
  65.     NAME */
  66.     #include <exec/memory.h>
  67.     #include <clib/exec_protos.h>
  68.  
  69.     AROS_LH2(void, FreeMem,
  70.  
  71. /*  SYNOPSIS */
  72.     AROS_LHA(APTR,  memoryBlock, A1),
  73.     AROS_LHA(ULONG, byteSize,    D0),
  74.  
  75. /*  LOCATION */
  76.     struct ExecBase *, SysBase, 35, Exec)
  77.  
  78. /*  FUNCTION
  79.     Give a block of memory back to the system pool.
  80.  
  81.     INPUTS
  82.     memoryBlock - Pointer to the memory to be freed
  83.     byteSize    - Size of the block
  84.  
  85.     RESULT
  86.  
  87.     NOTES
  88.  
  89.     EXAMPLE
  90.  
  91.     BUGS
  92.  
  93.     SEE ALSO
  94.     AllocMem()
  95.  
  96.     INTERNALS
  97.  
  98.     HISTORY
  99.     8-10-95    created by m. fleischer
  100.        16-10-95    increased portability
  101.  
  102. ******************************************************************************/
  103. {
  104.     AROS_LIBFUNC_INIT
  105.  
  106.     struct MemHeader *mh;
  107.     struct MemChunk *p1, *p2, *p3;
  108.     UBYTE *p4;
  109.  
  110.     D(bug("Call FreeMem (%08lx, %ld)\n", memoryBlock, byteSize));
  111.  
  112.     /* If there is no memory free nothing */
  113.     if(!byteSize)
  114.     ReturnVoid ("FreeMem");
  115.  
  116.     RT_Free (RTT_MEMORY, memoryBlock, byteSize);
  117.  
  118.     /* Align size to the requirements */
  119.     byteSize+=(IPTR)memoryBlock&(MEMCHUNK_TOTAL-1);
  120.     byteSize=(byteSize+MEMCHUNK_TOTAL-1)&~(MEMCHUNK_TOTAL-1);
  121.  
  122.     /* Align the block as well */
  123.     memoryBlock=(APTR)((IPTR)memoryBlock&~(MEMCHUNK_TOTAL-1));
  124.  
  125.     /* Start and end(+1) of the block */
  126.     p3=(struct MemChunk *)memoryBlock;
  127.     p4=(UBYTE *)p3+byteSize;
  128.  
  129.     /* Protect the memory list from access by other tasks. */
  130.     Forbid();
  131.  
  132.     /* Loop over MemHeader structures */
  133.     mh=(struct MemHeader *)SysBase->MemList.lh_Head;
  134.     while(mh->mh_Node.ln_Succ)
  135.     {
  136.     /* Test if the memory belongs to this MemHeader. */
  137.     if(mh->mh_Lower<=memoryBlock&&mh->mh_Upper>memoryBlock)
  138.     {
  139. #if !defined(NO_CONSISTENCY_CHECKS)
  140.         /* Test if it really fits into this MemHeader. */
  141.         if((APTR)p4>mh->mh_Upper)
  142.         /* Something is completely wrong. */
  143.         Alert(AN_MemCorrupt|AT_DeadEnd);
  144. #endif
  145.         /*
  146.         The free memory list is only single linked, i.e. to insert
  147.         elements into the list I need the node as well as it's
  148.         predessor. For the first element I can use freeList->mh_First
  149.         instead of a real predessor.
  150.         */
  151.         p1=(struct MemChunk *)&mh->mh_First;
  152.         p2=p1->mc_Next;
  153.  
  154.         /* No chunk in list? Just insert the current one and return. */
  155.         if(p2==NULL)
  156.         {
  157. #if NASTY_FREEMEM
  158.         PurgeChunk ((ULONG *)p3, byteSize);
  159. #endif
  160.         p3->mc_Bytes=byteSize;
  161.         p3->mc_Next=NULL;
  162.         p1->mc_Next=p3;
  163.         mh->mh_Free+=byteSize;
  164.         Permit ();
  165.         ReturnVoid ("FreeMem");
  166.         }
  167.  
  168.         /* Follow the list to find a place where to insert our memory. */
  169.         do
  170.         {
  171. #if !defined(NO_CONSISTENCY_CHECKS)
  172.         /*
  173.             Do some constistency checks:
  174.             1. All MemChunks must be aligned to
  175.                MEMCHUNK_TOTAL.
  176.             2. The end (+1) of the current MemChunk
  177.                must be lower than the start of the next one.
  178.         */
  179.         if(  ((IPTR)p2|p2->mc_Bytes)&(MEMCHUNK_TOTAL-1)
  180.             ||(  (UBYTE *)p2+p2->mc_Bytes>=(UBYTE *)p2->mc_Next
  181.             &&p2->mc_Next!=NULL))
  182.             Alert(AN_MemCorrupt|AT_DeadEnd);
  183. #endif
  184.         /* Found a block with a higher address? */
  185.         if(p2>=p3)
  186.         {
  187. #if !defined(NO_CONSISTENCY_CHECKS)
  188.             /*
  189.             If the memory to be freed overlaps with the current
  190.             block something must be wrong.
  191.             */
  192.             if(p4>(UBYTE *)p2)
  193.             Alert(AN_FreeTwice|AT_DeadEnd);
  194. #endif
  195.             /* End the loop with p2 non-zero */
  196.             break;
  197.         }
  198.         /* goto next block */
  199.         p1=p2;
  200.         p2=p2->mc_Next;
  201.  
  202.         /* If the loop ends with p2 zero add it at the end. */
  203.         }while(p2!=NULL);
  204.  
  205.         /* If there was a previous block merge with it. */
  206.         if(p1!=(struct MemChunk *)&mh->mh_First)
  207.         {
  208. #if !defined(NO_CONSISTENCY_CHECKS)
  209.         /* Check if they overlap. */
  210.         if((UBYTE *)p1+p1->mc_Bytes>(UBYTE *)p3)
  211.             Alert(AN_FreeTwice|AT_DeadEnd);
  212. #endif
  213.         /* Merge if possible */
  214.         if((UBYTE *)p1+p1->mc_Bytes==(UBYTE *)p3)
  215.             p3=p1;
  216.         else
  217.             /* Not possible to merge */
  218.             p1->mc_Next=p3;
  219.         }else
  220.         /*
  221.             There was no previous block. Just insert the memory at
  222.             the start of the list.
  223.         */
  224.         p1->mc_Next=p3;
  225.  
  226.         /* Try to merge with next block (if there is one ;-) ). */
  227.         if(p4==(UBYTE *)p2&&p2!=NULL)
  228.         {
  229.         /*
  230.             Overlap checking already done. Doing it here after
  231.             the list potentially changed would be a bad idea.
  232.         */
  233.         p4+=p2->mc_Bytes;
  234.         p2=p2->mc_Next;
  235.         }
  236.         /* relink the list and return. */
  237. #if NASTY_FREEMEM
  238.         PurgeChunk ((ULONG *)p3, p4-(UBYTE *)p3);
  239. #endif
  240.         p3->mc_Next=p2;
  241.         p3->mc_Bytes=p4-(UBYTE *)p3;
  242.         mh->mh_Free+=byteSize;
  243.         Permit();
  244.         ReturnVoid ("FreeMem");
  245.     }
  246.     mh=(struct MemHeader *)mh->mh_Node.ln_Succ;
  247.     }
  248.  
  249. #if !defined(NO_CONSISTENCY_CHECKS)
  250.     /* Some memory that didn't fit into any MemHeader? */
  251.     Alert(AN_MemCorrupt|AT_DeadEnd);
  252. #else
  253.     Permit();
  254. #endif
  255.  
  256.     ReturnVoid ("FreeMem");
  257.     AROS_LIBFUNC_EXIT
  258. } /* FreeMem */
  259.  
  260.